import threading

import cv2
import loguru

try:
    from .MvImport import *
except FileNotFoundError:
    loguru.logger.warning("未检测到Hik摄像头驱动")
from .camera_interface import CameraInterface


class HIKCamera(CameraInterface):
    def __init__(self):
        super().__init__()
        self.device_list = MV_CC_DEVICE_INFO_LIST()
        self.cam = MvCamera()
        self.nSelCamIndex = 0
        self.obj_cam_operation = 0
        self.isOpen = False
        self.isGrabbing = False
        self.isCalibMode = True

    def open_camera(self):
        # 枚举相机
        ret = MvCamera.MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, self.device_list)
        if ret != 0:
            print("enum devices fail! ret[0x%x]" % ret)
            sys.exit()
        stDeviceList = cast(self.device_list.pDeviceInfo[int(0)], POINTER(MV_CC_DEVICE_INFO)).contents
        # 打开相机
        ret = self.cam.MV_CC_CreateHandle(stDeviceList)
        if ret != 0:
            print("create handle fail! ret[0x%x]" % ret)
            sys.exit()
        # ch:打开设备 | en:Open device
        ret = self.cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
        if ret != 0:
            print("open device fail! ret[0x%x]" % ret)
            sys.exit()
        self.camera_setting("TriggerMode", MV_TRIGGER_MODE_OFF)
        self.camera_setting('PixelFormat', PixelType_Gvsp_YUV422_Packed)
        self.camera_setting('GainAuto', MV_GAIN_MODE_CONTINUOUS)
        self.camera_setting('ExposureTime', 3000, mode='float')

        self.cam.MV_CC_StartGrabbing()
        threading.Thread(target=self.work_thread_1).start()

    def IsImageColor(self, enType):
        dates = {
            PixelType_Gvsp_RGB8_Packed: 'color',
            PixelType_Gvsp_BGR8_Packed: 'color',
            PixelType_Gvsp_YUV422_Packed: 'color',
            PixelType_Gvsp_YUV422_YUYV_Packed: 'color',
            PixelType_Gvsp_BayerGR8: 'color',
            PixelType_Gvsp_BayerRG8: 'color',
            PixelType_Gvsp_BayerGB8: 'color',
            PixelType_Gvsp_BayerBG8: 'color',
            PixelType_Gvsp_BayerGB10: 'color',
            PixelType_Gvsp_BayerGB10_Packed: 'color',
            PixelType_Gvsp_BayerBG10: 'color',
            PixelType_Gvsp_BayerBG10_Packed: 'color',
            PixelType_Gvsp_BayerRG10: 'color',
            PixelType_Gvsp_BayerRG10_Packed: 'color',
            PixelType_Gvsp_BayerGR10: 'color',
            PixelType_Gvsp_BayerGR10_Packed: 'color',
            PixelType_Gvsp_BayerGB12: 'color',
            PixelType_Gvsp_BayerGB12_Packed: 'color',
            PixelType_Gvsp_BayerBG12: 'color',
            PixelType_Gvsp_BayerBG12_Packed: 'color',
            PixelType_Gvsp_BayerRG12: 'color',
            PixelType_Gvsp_BayerRG12_Packed: 'color',
            PixelType_Gvsp_BayerGR12: 'color',
            PixelType_Gvsp_BayerGR12_Packed: 'color',
            PixelType_Gvsp_Mono8: 'mono',
            PixelType_Gvsp_Mono10: 'mono',
            PixelType_Gvsp_Mono10_Packed: 'mono',
            PixelType_Gvsp_Mono12: 'mono',
            PixelType_Gvsp_Mono12_Packed: 'mono'}
        return dates.get(enType, '未知')

    def image_show(self, image):
        image = cv2.resize(image, (600, 400), interpolation=cv2.INTER_AREA)
        # cv2.imshow('fgmask', image)
        # cv2.waitKey(1) & 0xff

    def image_control(self, data, stFrameInfo):
        if stFrameInfo.enPixelType == 17301505:
            image = data.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))
            self.image_show(image=image)
        elif stFrameInfo.enPixelType == 17301514:
            data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
            image = cv2.cvtColor(data, cv2.COLOR_BAYER_GB2RGB)
            self.image_show(image=image)
        elif stFrameInfo.enPixelType == 35127316:
            data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
            image = cv2.cvtColor(data, cv2.COLOR_RGB2BGR)
            self.image_show(image=image)
        elif stFrameInfo.enPixelType == 34603039:
            data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)
            image = cv2.cvtColor(data, cv2.COLOR_YUV2BGR_Y422)
            self.image_show(image=image)
        self.frame = image

    def work_thread_1(self):
        stParam = MVCC_INTVALUE_EX()
        memset(byref(stParam), 0, sizeof(MVCC_INTVALUE_EX))
        ret = self.cam.MV_CC_GetIntValueEx("PayloadSize", stParam)
        if ret != 0:
            print("get payload size fail! ret[0x%x]" % ret)
            sys.exit()
        nDataSize = stParam.nCurValue
        pData = (c_ubyte * nDataSize)()
        stFrameInfo = MV_FRAME_OUT_INFO_EX()
        memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
        print('start get frame')
        while True:
            if self.kill_record_thread:
                break
            ret = self.cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
            if ret == 0:
                # print("get one frame: Width[%d], Height[%d], nFrameNum[%d] " % (
                #     stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))
                image = np.asarray(pData)
                self.image_control(data=image, stFrameInfo=stFrameInfo)

            else:
                print("no data[0x%x]" % ret)

    def camera_setting(self, key, value, mode='enum'):
        ret = -1
        if mode == 'enum':
            ret = self.cam.MV_CC_SetEnumValue(key, value)
        if mode == 'float':
            ret = self.cam.MV_CC_SetFloatValue(key, value)
        if ret != 0:
            print(f"set {key} fail! ret[0x%x]" % ret)

    def close_camera(self):
        super().close_camera()
        # ch:停止取流 | en:Stop grab image
        ret = self.cam.MV_CC_StopGrabbing()
        if ret != 0:
            print("stop grabbing fail! ret[0x%x]" % ret)
            sys.exit()

        # ch:关闭设备 | Close device
        ret = self.cam.MV_CC_CloseDevice()
        if ret != 0:
            print("close deivce fail! ret[0x%x]" % ret)
            sys.exit()
        ret = self.cam.MV_CC_DestroyHandle()
        if ret != 0:
            print("destroy handle fail! ret[0x%x]" % ret)
            sys.exit()


if __name__ == '__main__':
    hik = HIKCamera()
    hik.open_camera()
    while True:
        frame = hik.get_frame()
        if frame is not None:
            frame = cv2.resize(frame, (600, 400), interpolation=cv2.INTER_AREA)
            cv2.imshow('window',frame)
        cv2.waitKey(1)

